#include "power.h"

#include "accelerometer.h"
#include "display.h"
#include "error.h"
#include "device.h"
#include "iap.h"
#include "reports.h"
#include <stm32f10x_it.h>
#include "usb.h"
#include "version.h"

#define	MAX_SUM	20000

static uint	rank,tkChg0,tkChg1;
static ushort volt;

static ubyte calc(void){
	if(rank)
		return rank;
	short res=reports.voltCV-reports.voltSV+250;
	if(res<0)
		res=0;
	res=res*3/200;
	if(res>3)
		res=3;
	return res+1;
}
static void chargeBegin(void){
	tkChg0=RTC_GetCounter();
	rank=tkChg1=0;
}
static void chargeEnd(void){
	uint t=RTC_GetCounter();
	reports.tkChgLV=t;
	reports.tkChgHV=t>>16;
	if(tkChg1){
		reports.tcChgCV=tkChg1-tkChg0;
		t-=tkChg1;
		reports.tcChgVV=t>0xffff?0xffff:t;
	}else{
		reports.tcChgCV=t-tkChg0;
		reports.tcChgVV=0;
	}
}

//------------------------------------------------------------------------------

void ADC1_2_IRQHandler(void){
	static uint cnt=MAX_SUM,sum;
	if(ADC_GetITStatus(ADC1,ADC_IT_EOC)){
		volt=ADC_GetConversionValue(ADC1);
		sum+=volt;
		if(!(--cnt)){
			sum/=MAX_SUM;
			reports.voltCV=sum;
			uint t=RTC_GetCounter();
			if(tkChg1){
				t-=tkChg1;
				rank=t>3000?7:t/1000+4;
			}else if(t-tkChg0>4500 || sum>reports.voltSV-13){
				tkChg1=t;
				reports.tcChgCV=t-tkChg0;
				reports.voltSV=sum;
			}
			if(sum>reports.voltSV)
				reports.voltSV=sum;
			cnt=MAX_SUM;
			sum=0;
		}
		ADC_ClearITPendingBit(ADC1,ADC_IT_EOC);
	}
}

//------------------------------------------------------------------------------

void charging(void){
	display_on();
	display_battery(0);
	//checkVecTable();
	chargeBegin();
	meterOn();
	while(status==STATUS_CHARGING){
		if(powerSignal())
			PWR_EnterSTANDBYMode();
		report();
		display_battery(calc());
		__WFI();
		dispatch();
		ubyte s=getStatusEx(prepare);
		if(s!=STATUS_TAP)
			status=s;
	}
	meterOff();
	chargeEnd();
	lowPower=0;
}
ubyte powerSignal(void){
	return volt && volt<VOLT_B;
}
void meterOff(void){
	ADC_Cmd(ADC1,DISABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,DISABLE);
}
void meterOn(void){
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
	RCC_ADCCLKConfig(RCC_PCLK2_Div8);
	ADC_InitTypeDef a;
	a.ADC_Mode				=ADC_Mode_Independent;
	a.ADC_ScanConvMode		=DISABLE;
	a.ADC_ContinuousConvMode=DISABLE;
	a.ADC_ExternalTrigConv	=ADC_ExternalTrigConv_None;
	a.ADC_DataAlign			=ADC_DataAlign_Right;
	a.ADC_NbrOfChannel		=1;
	ADC_Init(ADC1,&a);
	ADC_ITConfig(ADC1,ADC_IT_EOC,ENABLE);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_7Cycles5);
	ADC_Cmd(ADC1,ENABLE);
	volt=0;
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);
}
